package com.yctan.base.controller;


import com.ns.medicinecloud.base.utils.DateUtils;
import com.ns.medicinecloud.data.entity.Container;
import com.ns.medicinecloud.data.service.ContainerDrugService;
import com.ns.medicinecloud.data.service.ContainerService;
import com.ns.medicinecloud.transaction.entity.OrderForm;
import com.ns.medicinecloud.transaction.entity.OrderFormDetails;
import com.ns.medicinecloud.transaction.service.OrderFormService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.*;

/**
 * @ClassName 启动时缓存一些数据
 * @Description TODO
 * @Date 2020/3/23
 */
@Component
public class CodeCache {
    private final OrderFormService orderFormService;
    private final ContainerService containerService;
    private final ContainerDrugService containerDrugService;

    public static Map<Integer, Date> heartbeatMap = new HashMap<>();

    /**
     * 日志对象
     */
    protected Logger logger = LoggerFactory.getLogger(getClass());

    public CodeCache(OrderFormService orderFormService, ContainerService containerService, ContainerDrugService containerDrugService) {
        this.orderFormService = orderFormService;
        this.containerService = containerService;
        this.containerDrugService = containerDrugService;
    }


    @PostConstruct
    public void init() {
        //系统启动中。。。
        logger.info("项目启动中");
        initializeHeartbeat();
    }

    @PreDestroy
    public void destroy() {
        //系统运行结束
    }

    //更新药品销量
    public void updDrug() {
        OrderForm orderForm = new OrderForm();
        //一个月以前
        orderForm.setEndQueryDate(DateUtils.AMonthAgo());
        //当天
        orderForm.setEndQueryDate(new Date());
        //更新销量
        orderFormService.monthlySales(orderForm);
    }

    //初始化心跳
    public void initializeHeartbeat() {
        logger.info("开始初始化心跳");
        Container container = new Container();
        container.setState(1);
        List<Map<String, Object>> list = containerService.dropBox(container);
        for (Map<String, Object> map : list) {
            Integer id = Integer.valueOf(map.get("id").toString());
            CodeCache.heartbeatMap.put(id, new Date());
        }
    }

    //每天凌晨两点
    @Async
    @Scheduled(cron = "0 0 2 * * ?")
    public void testOne() {
        //更新销量
        updDrug();
    }

    /**
     * 检查智能柜心跳方法
     * 启动后60*10秒开始执行，距离上次执行结束之后60*30秒再开始执行下一次
     */
    @Scheduled(initialDelay = 600000, fixedDelay = 1800000)
    @Async
    public void heartbeat() {
        logger.info("【定时任务，检查智能柜心跳】开始检查");
        Iterator<Map.Entry<Integer, Date>> it = CodeCache.heartbeatMap.entrySet().iterator();
        List<Integer> list = new ArrayList<>();
        int number = 0;
        while (it.hasNext()) {
            Map.Entry<Integer, Date> entry = it.next();
            //过去的分钟数
            long min = DateUtils.pastMinutes(entry.getValue());
            if (min > 35) {
                number++;
                list.add(entry.getKey());
                logger.error("【定时任务，检查智能柜心跳】智能柜id" + entry.getKey() + ":,已经" + min + "分钟没有发送报告了");
                if (min < 60) {
                    //只有第一次发送短信
                    containerService.sendSms(entry.getKey());
                }
            }
        }
        if (list.size() > 0) {
            //批量修改智能柜为维护中
            containerService.updMaintenance(list);

        }
        logger.info("【定时任务，检查智能柜心跳】检查完成," + number + "个智能柜失联");
    }

    /**
     * 定时把过期订单变成已取消
     * 启动后10秒开始执行，距离上次执行结束之后60*30秒再开始执行下一次
     * 订单5-15分钟过期
     * 30分钟查询一次，查询50-15分钟前的订单
     */
    @Scheduled(initialDelay = 10000, fixedDelay = 1800000)
    @Async
    public void backOrder() {
        logger.info("【定时任务，检查过期订单】开始检查");
        OrderForm orderForm = new OrderForm();
        //当前时间50分钟前
        Date startQueryDate = DateUtils.getBeforeMinutes(new Date(), -50);
        Date endQueryDate = DateUtils.getBeforeMinutes(new Date(), -15);
        Date[] dateQueryScope = new Date[2];
        dateQueryScope[0] = startQueryDate;
        dateQueryScope[1] = endQueryDate;
        //查询时间
        orderForm.setDateQueryScope(dateQueryScope);
        //只查询未支付
        orderForm.setStatus(0);
        List<OrderForm> list = orderFormService.findListNotDetails(orderForm);
        //需要恢复的货架map
        Map<Integer, Integer> recoverMap = new HashMap<>();
        if (list != null) {
            List<Integer> updList = new ArrayList<>();
            for (OrderForm order : list) {
                if (order.judgeExpiration()) {
                    //过期了，改成取消
                    updList.add(order.getId());
                    //获取需要恢复的药品数量
                    if (order.getOrderFormDetailsList() != null) {
                        //获取需要恢复的药品数量
                        for (OrderFormDetails orderFormDetails : order.getOrderFormDetailsList()) {
                            //货架id
                            Integer id = orderFormDetails.getGoodsShelf().getId();
                            //药品数量
                            Integer number = orderFormDetails.getNumber();
                            if (recoverMap.get(id) == null) {
                                recoverMap.put(id, number);
                            } else {
                                recoverMap.put(id, recoverMap.get(id) + number);
                            }
                        }
                    }
                }
            }
            if (updList.size() > 0) {
                //批量修改订单状态为取消
                orderFormService.updCallOffList(updList);
                //批量恢复药品数量
                containerDrugService.recoverNumberList(recoverMap);
            }
        }
        logger.info("【定时任务，检查过期订单】检查完成，已将过期订单修改为取消");
    }


}
